home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / pcxtoppm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-10  |  8.2 KB  |  356 lines

  1. /*
  2.  * pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
  3.  *
  4.  * Copyright (c) 1990 by Michael Davidson
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and that
  9.  * both that copyright notice and this permission notice appear in
  10.  * supporting documentation.
  11.  *
  12.  * This file is provided AS IS with no warranties of any kind.  The author
  13.  * shall have no liability with respect to the infringement of copyrights,
  14.  * trade secrets or any patents by this file or any part thereof.  In no
  15.  * event will the author be liable for any lost revenue or profits or
  16.  * other special, indirect and consequential damages.
  17.  *
  18.  */
  19.  
  20. #include    <stdio.h>
  21. #include    "ppm.h"
  22.  
  23. #define    PCX_MAGIC    0x0a        /* PCX magic number        */
  24. #define    PCX_HDR_SIZE    128        /* size of PCX header        */
  25. #define    PCX_256_COLORS    0x0c        /* magic number for 256 colors    */
  26.  
  27. #define    MAXCOLORS       256
  28. #define    MAXPLANES    4
  29. #define    PCX_MAXVAL    255
  30.  
  31. static void read_pcx_image ARGS(( FILE *fp, unsigned char *buf, int BytesPerLine, int Planes, int Height ));
  32. static void pcx_planes_to_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  33. static void pcx_unpack_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  34. static int GetByte ARGS(( FILE *fp ));
  35. static int GetWord ARGS(( FILE *fp ));
  36.  
  37. void
  38. main(argc, argv)
  39.     int        argc;
  40.     char    *argv[];
  41. {
  42.     register int    i;
  43.     FILE        *ifp;
  44.     char        *ifname;
  45.     int            Version;
  46.     int            Xmin, Ymin, Xmax, Ymax;
  47.     int            Width, Height;
  48.     register int    x, y;
  49.     int            Planes;
  50.     int            BitsPerPixel;
  51.     int            BytesPerLine;
  52.     unsigned char    Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  53.     unsigned char    *pcximage;
  54.     unsigned char    *pcxplanes;
  55.     unsigned char    *pcxpixels;
  56.     pixel        **pixels;
  57.  
  58.     ppm_init( &argc, argv );
  59.  
  60.     switch (argc)
  61.     {
  62.      case 1:
  63.          ifname    = "standard input";
  64.          ifp    = stdin;
  65.          break;
  66.      case 2:
  67.          ifname    = argv[1];
  68.          ifp    = pm_openr(ifname);
  69.          break;
  70.      default:
  71.          pm_usage("[pcxfile]");
  72.          break;
  73.     }
  74.  
  75.     /*
  76.      * read the PCX header
  77.      */
  78.     if (GetByte(ifp) != PCX_MAGIC)
  79.      pm_error("%s is not a PCX file", ifname );
  80.  
  81.     Version    = GetByte(ifp);     /* get version #            */
  82.  
  83.     if (GetByte(ifp) != 1)     /* check for PCX run length encoding    */
  84.      pm_error("%s has unknown encoding scheme", ifname );
  85.  
  86.     BitsPerPixel= GetByte(ifp);
  87.     Xmin    = GetWord(ifp);
  88.     Ymin    = GetWord(ifp);
  89.     Xmax    = GetWord(ifp);
  90.     Ymax    = GetWord(ifp);
  91.  
  92.     Width    = (Xmax - Xmin) + 1;
  93.     Height    = (Ymax - Ymin) + 1;
  94.  
  95.     (void) GetWord(ifp);        /* ignore horizontal resolution    */
  96.     (void) GetWord(ifp);        /* ignore vertical resolution    */
  97.  
  98.     /*
  99.      * get the 16-color color map
  100.      */
  101.     for (i = 0; i < 16; i++)
  102.     {
  103.      Red[i]       = GetByte(ifp);
  104.      Green[i]  = GetByte(ifp);
  105.      Blue[i]   = GetByte(ifp);
  106.     }
  107.  
  108.     (void) GetByte(ifp);        /* skip reserved byte     */
  109.     Planes    = GetByte(ifp);        /* # of color planes     */
  110.     BytesPerLine= GetWord(ifp);        /* # of bytes per line     */
  111.     (void) GetWord(ifp);        /* ignore palette info     */
  112.  
  113.     /*
  114.      * check that we can handle this image format
  115.      */
  116.     switch (BitsPerPixel)
  117.     {
  118.     case 1:
  119.         if (Planes > 4)
  120.         pm_error("can't handle image with more than 4 planes");
  121.         break;
  122.  
  123.     case 2:
  124.     case 4:
  125.     case 8:
  126.         if (Planes == 1)
  127.         break;
  128.     default:
  129.         pm_error("can't handle %d bits per pixel image with %d planes",
  130.             BitsPerPixel,Planes);
  131.     }
  132.  
  133.  
  134.     /*
  135.      * read the pcx format image
  136.      */
  137.     fseek(ifp, (long)PCX_HDR_SIZE, 0);
  138.     pcximage    = (unsigned char *)pm_allocrow(BytesPerLine * Planes, Height);
  139.     read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
  140.  
  141.     /*
  142.      * 256 color images have their color map at the end of the file
  143.      * preceeded by a magic byte
  144.      */
  145.     if (BitsPerPixel == 8)
  146.     {
  147.     if (GetByte(ifp) != PCX_256_COLORS)
  148.         pm_error("bad color map signature" );
  149.  
  150.     for (i = 0; i < MAXCOLORS; i++)
  151.     {
  152.         Red[i]    = GetByte(ifp);
  153.         Green[i]    = GetByte(ifp);
  154.         Blue[i]    = GetByte(ifp);
  155.     }
  156.     }
  157.  
  158.     pixels    = ppm_allocarray(Width, Height);
  159.     pcxpixels    = (unsigned char *)pm_allocrow(Width+7, 1);
  160.  
  161.     /*
  162.      * convert the image
  163.      */
  164.     for (y = 0; y < Height; y++)
  165.     {
  166.      pcxplanes = pcximage + (y * BytesPerLine * Planes);
  167.  
  168.      if (Planes == 1)
  169.      {
  170.          pcx_unpack_pixels(pcxpixels, pcxplanes,
  171.           BytesPerLine, Planes, BitsPerPixel);
  172.      }
  173.      else
  174.      {
  175.          pcx_planes_to_pixels(pcxpixels, pcxplanes,
  176.           BytesPerLine, Planes, BitsPerPixel);
  177.      }
  178.  
  179.      for (x = 0; x < Width; x++)
  180.      {
  181.          i = pcxpixels[x];
  182.          PPM_ASSIGN(pixels[y][x], Red[i], Green[i], Blue[i]);
  183.      }
  184.     }
  185.  
  186.     pm_close(ifp);
  187.  
  188.     ppm_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );
  189.  
  190.     pm_close(stdout);
  191.  
  192.     exit(0);
  193. }
  194.  
  195. static void
  196. read_pcx_image(fp, buf, BytesPerLine, Planes, Height)
  197.     FILE    *fp;
  198.     unsigned char   *buf;
  199.     int         BytesPerLine;
  200.     int         Planes;
  201.     int         Height;
  202. {
  203.     int        c;
  204.     int        nbytes;
  205.     int        count;
  206.  
  207.     nbytes    = BytesPerLine * Planes * Height;
  208.  
  209.     while (nbytes > 0)
  210.     {
  211.      c    = GetByte(fp);
  212.      if ((c & 0xc0) != 0xc0)
  213.      {
  214.          *buf++    = c;
  215.          --nbytes;
  216.          continue;
  217.      }
  218.  
  219.      count    = c & 0x3f;
  220.      c    = GetByte(fp);
  221.      if (count > nbytes)
  222.          pm_error("repeat count spans end of image, count = %d, nbytes = %d", count, nbytes);
  223.  
  224.      nbytes    -= count;
  225.      while (--count >= 0)
  226.          *buf++ = c;
  227.     }
  228. }
  229.  
  230. /*
  231.  * convert multi-plane format into 1 pixel per byte
  232.  */
  233. static void
  234. pcx_planes_to_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  235. unsigned char    *pixels;
  236. unsigned char    *bitplanes;
  237. int        bytesperline;
  238. int         planes;
  239. int         bitsperpixel;
  240. {
  241.     int     i, j;
  242.     int     npixels;
  243.     unsigned char    *p;
  244.  
  245.     if (planes > 4)
  246.      pm_error("can't handle more than 4 planes" );
  247.     if (bitsperpixel != 1)
  248.      pm_error("can't handle more than 1 bit per pixel" );
  249.  
  250.     /*
  251.      * clear the pixel buffer
  252.      */
  253.     npixels = (bytesperline * 8) / bitsperpixel;
  254.     p    = pixels;
  255.     while (--npixels >= 0)
  256.      *p++ = 0;
  257.  
  258.     /*
  259.      * do the format conversion
  260.      */
  261.     for (i = 0; i < planes; i++)
  262.     {
  263.      int pixbit, bits, mask;
  264.  
  265.      p    = pixels;
  266.      pixbit    = (1 << i);
  267.      for (j = 0; j < bytesperline; j++)
  268.      {
  269.          bits = *bitplanes++;
  270.          for (mask = 0x80; mask != 0; mask >>= 1, p++)
  271.           if (bits & mask)
  272.               *p |= pixbit;
  273.      }
  274.      }
  275. }
  276.  
  277. /*
  278.  * convert packed pixel format into 1 pixel per byte
  279.  */
  280. static void
  281. pcx_unpack_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  282. unsigned char   *pixels;
  283. unsigned char   *bitplanes;
  284. int        bytesperline;
  285. int         planes;
  286. int         bitsperpixel;
  287. {
  288.     register int    bits;
  289.  
  290.     if (planes != 1)
  291.      pm_error("can't handle packed pixels with more than 1 plane" );
  292.     if (bitsperpixel == 8)
  293.     {
  294.     while (--bytesperline >= 0)
  295.         *pixels++ = *bitplanes++;
  296.     }
  297.     else if (bitsperpixel == 4)
  298.     {
  299.     while (--bytesperline >= 0)
  300.     {
  301.         bits    = *bitplanes++;
  302.         *pixels++    = (bits >> 4) & 0x0f;
  303.         *pixels++    = (bits     ) & 0x0f;
  304.     }
  305.     }
  306.     else if (bitsperpixel == 2)
  307.     {
  308.     while (--bytesperline >= 0)
  309.     {
  310.         bits    = *bitplanes++;
  311.         *pixels++    = (bits >> 6) & 0x03;
  312.         *pixels++    = (bits >> 4) & 0x03;
  313.         *pixels++    = (bits >> 2) & 0x03;
  314.         *pixels++    = (bits     ) & 0x03;
  315.     }
  316.     }
  317.     else if (bitsperpixel == 1)
  318.     {
  319.     while (--bytesperline >= 0)
  320.     {
  321.         bits    = *bitplanes++;
  322.         *pixels++    = ((bits & 0x80) != 0);
  323.         *pixels++    = ((bits & 0x40) != 0);
  324.         *pixels++    = ((bits & 0x20) != 0);
  325.         *pixels++    = ((bits & 0x10) != 0);
  326.         *pixels++    = ((bits & 0x08) != 0);
  327.         *pixels++    = ((bits & 0x04) != 0);
  328.         *pixels++    = ((bits & 0x02) != 0);
  329.         *pixels++    = ((bits & 0x01) != 0);
  330.     }
  331.     }
  332. }
  333.  
  334. static int
  335. GetByte(fp)
  336. FILE    *fp;
  337. {
  338.     int    c;
  339.  
  340.     if ((c = getc(fp)) == EOF)
  341.      pm_error("unexpected end of file" );
  342.  
  343.     return c;
  344. }
  345.  
  346. static int
  347. GetWord(fp)
  348. FILE    *fp;
  349. {
  350.     int    c;
  351.  
  352.     c  = GetByte(fp);
  353.     c |= (GetByte(fp) << 8);
  354.     return c;
  355. }
  356.